package cn.jdemo.core.javassist;

import javassist.*;

/**
 * ClassPool：javassist的类池，使用ClassPool 类可以跟踪和控制所操作的类，它的工作方式与 JVM 类装载器非常相似
 *
 * CtClass： CtClass提供了类的操作，如在类中动态添加新字段、方法和构造函数、以及改变类、父类和接口的方法。
 *
 * CtField：类的属性，通过它可以给类创建新的属性，还可以修改已有的属性的类型，访问修饰符等
 *
 * CtMethod：类中的方法，通过它可以给类创建新的方法，还可以修改返回类型，访问修饰符等， 甚至还可以修改方法体内容代码
 *
 * CtConstructor：与CtMethod类似
 *
 */
public class App {
    public static void main(String[] args) throws Exception {
        doJavaAssist1();
    }

    private static void doJavaAssist1() throws Exception {
        // 类库, jvm中所加载的class
        ClassPool pool = ClassPool.getDefault();
        // 创建一个新的类, 类名必须为全量类名
        CtClass clzNew = pool.makeClass("cn.jdemo.core.javassist.Person");

        /* 构建成员变量 */
        CtField other = new CtField(CtClass.intType,"other",clzNew);
        other.setModifiers(Modifier.PRIVATE);
        CtField nickName = new CtField(pool.get("java.lang.String"), "nickName", clzNew);
        nickName.setModifiers(Modifier.PROTECTED);
        CtField age = CtField.make("private int age;", clzNew);

        //创建新的方法, 参数1:方法的返回类型，参数2：名称，参数3：方法的参数，参数4：方法所属的类
        CtMethod ctMethodNew = new CtMethod(CtClass.intType, "cacSum", new CtClass[]{CtClass.intType, CtClass.intType}, clzNew);
        ctMethodNew.setModifiers(Modifier.PUBLIC);
        ctMethodNew.setBody("return $1 + $2;");// 方法体内容代码 $1代表第一个参数，$2代表第二个参数

        // 将属性添加到类中,并赋初始值
        clzNew.addField(other,"0");
        clzNew.addField(nickName,"狗子");
        clzNew.addField(age,"10");
        // 将新建的方法添加到类中
        clzNew.addMethod(ctMethodNew);
        // 快速创建getset方法
        clzNew.addMethod(CtNewMethod.setter("setNickName", other));
        clzNew.addMethod(CtNewMethod.getter("getNickName", nickName));
        clzNew.addMethod(CtNewMethod.setter("setAge",age));
        clzNew.addMethod(CtNewMethod.getter("getAge",age));

        clzNew.addConstructor(new CtConstructor(null,clzNew));

        clzNew.writeFile("D:\\gm\\code\\jdemo\\jdemo\\jdemo-core\\src\\main\\java");
    }
}
